package com.swgk.core.base.api;

import android.accounts.NetworkErrorException;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.swgk.core.BaseAppApplication;
import com.swgk.core.BaseAppHelper;
import com.swgk.core.BuildConfig;
import com.swgk.core.base.model.entity.BaseEntity;
import com.swgk.core.dialog.DialogHelper;
import com.swgk.core.dialog.DialogHelperNew;
import com.swgk.core.event.LoginTokenEvent;
import com.swgk.core.helper.AppManagerHelper;
import com.swgk.core.util.MLog;
import com.swgk.core.util.MToast;
import com.swgk.core.util.SharedPreferenceUtil;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public abstract class ICallBack<T> implements Callback<T> {

    /**
     * 是否自动销毁默认联网弹框
     */
    private boolean isAutoDismissDialog = true;

    public abstract void onSuccess(T data);

    public void onFinally() {
        if (isAutoDismissDialog) {
            DialogHelper.dismissProgressDialog();
        }
    }

    public void onFail() {
    }

    public ICallBack() {
    }

    /**
     * 自动显示，是否自动关闭进度条
     * 使用此方法的时候，isAutoDismissDialog 默认值为true ，当为true时自动关闭并销毁 Dialog转圈，
     *
     * @param isAutoDismissDialog true，自动开，自动关
     */
    public ICallBack(boolean isAutoDismissDialog) {
        this(true, isAutoDismissDialog, false);
    }

    /**
     * 1.isAutoDialog = true && isAutoDismissDialog = true  自动显示，自动关闭
     * 1.isAutoDialog = true && isAutoDismissDialog = false  自动显示，不自动关闭
     * 2.isAutoDialog = false && isAutoDismissDialog = true  不自动显示转圈，但是会自动关闭
     * 3.isAutoDialog = false && isAutoDismissDialog = false  不自动显示转圈，但是不会自动关闭
     * 注意：使用此方法的时候，isAutoDialog 默认值为true，当为true时自动创建 Dialog转圈并且显示，当 isAutoDismissDialog 为true时才可自动销毁，否则不销毁
     *
     * @param isAutoDialog        是否自动创建，默认 false
     * @param isAutoDismissDialog 是否自动销毁，默认为 true
     */
    public ICallBack(boolean isAutoDialog, boolean isAutoDismissDialog) {
        this(isAutoDialog, isAutoDismissDialog, false);
    }

    /**
     * 1.isAutoDialog = true && isAutoDismissDialog = true  自动显示，自动关闭
     * 1.isAutoDialog = true && isAutoDismissDialog = false  自动显示，不自动关闭
     * 2.isAutoDialog = false && isAutoDismissDialog = true  不自动显示转圈，但是会自动关闭
     * 3.isAutoDialog = false && isAutoDismissDialog = false  不自动显示转圈，但是不会自动关闭
     * 注意：使用此方法的时候，isAutoDialog 默认值为true，当为true时自动创建 Dialog转圈并且显示，当 isAutoDismissDialog 为true时才可自动销毁，否则不销毁
     *
     * @param isAutoDialog        是否自动创建，默认 true
     * @param isAutoDismissDialog 是否自动销毁，默认为 true
     * @param isShowJump          是否是跳跳动画，默认为 false，默认转圈，否则为跳跳动画
     */
    public ICallBack(boolean isAutoDialog, boolean isAutoDismissDialog, boolean isShowJump) {
        init(isAutoDialog, isAutoDismissDialog, isShowJump);
    }

    /**
     * @param isAutoDialog        是否自动显示
     * @param isAutoDismissDialog 是否自动关闭
     * @param isShowJump          是否展示为动画模式
     */
    private void init(boolean isAutoDialog, boolean isAutoDismissDialog, boolean isShowJump) {
        this.isAutoDismissDialog = isAutoDismissDialog;
        if (isAutoDialog && BaseAppHelper.get().getActivity() != null) {
            if (!DialogHelper.isShowing()) {
                DialogHelper.showProgressDialog(BaseAppHelper.get().getActivity(), null, "数据加载中...", 0, false, isShowJump, null).setCanceledOnTouchOutside(false);
            }
        }
    }

    @Override
    public void onResponse(Call<T> call, Response<T> response) {
        if (BuildConfig.BUILD_TYPE.equals("release") && !BuildConfig.DEBUG) {
            try {
                onResponseRelest(call, response);
            } catch (Exception e) {
                onFailure(call, e);
            } finally {
                onFinally();
            }
        } else {
            onResponseRelest(call, response);
            onFinally();
        }
    }

    private void onResponseRelest(Call<T> call, Response<T> response) {
        String message = "";
        if (response.isSuccessful() && response.body() != null) {
            String url = response.raw().request().url().toString();
            BaseEntity body = (BaseEntity) response.body();
            if (body.getState().equals(APIManager.RESPONSE_OK)) {
                onSuccess(response.body());
                return;
            } else {
                MLog.e("api", "onFailure: 接口响应失败  url = " + url);
                //用于统一处理错误码code
                message = onFailureWithCode(body);
                //用于判断错误码code
                onFailureWithEntity(body);
            }
        } else {
            MLog.e("api", "onFailure: 接口响应失败  url = " + call.request().url().toString() + "body :  " + response.toString());
            message = "数据加载异常";
        }
        onFailure(call, new IOException(message));
    }

    @Override
    public void onFailure(Call<T> call, Throwable t) {
        //当时正式环境并未开启debug时，不捕获异常，否则抛出异常
        if (BuildConfig.BUILD_TYPE.equals("release") && !BuildConfig.DEBUG) {
            try {
                putException(call, t);
            } catch (Exception e) {
                MLog.e("接口解析错误，请检查接口数据格式和解析方式", e.toString());
            } finally {
                onFail();
                onFinally();
            }
        } else {
            try {
                putException(call, t);
                onFail();
                onFinally();
            } catch (Exception e) {
            }
        }
    }

    private void putException(Call<T> call, Throwable t) {
        String message = "";
        if (t instanceof ConnectException
                || t instanceof UnknownHostException) {
            message = "网络链接不稳定，请稍后重试";
        } else if (t instanceof NetworkErrorException) {
            message = "无网络，请检查网络连接";
        } else if (t instanceof SocketTimeoutException) {
            message = "网络连接超时，请稍后再试";
        } else if (t instanceof IOException) {
            if ("数据加载异常".equals(t.getMessage())) {
                message = "数据加载异常";
            } else if ("无网络，请检查网络连接".equals(t.getMessage())) {
                message = "无网络，请检查网络连接";
            } else if ("接口响应失败".equals(t.getMessage())) {
                if (BuildConfig.BUILD_TYPE.equals("release") && !BuildConfig.DEBUG) {
                    cleanTokenInfo();
                    message = "登录失效，请重新登录";
                } else {
                    message = "接口请求失败";
                }
            } else if (!TextUtils.isEmpty(t.getMessage()) &&
                    (t.getMessage().contains("请重新登录") || t.getMessage().contains("不允许访问"))) {
                cleanTokenInfo();
                message = "登录失效，请重新登录";
            } else {
                if (!TextUtils.isEmpty(t.getMessage())) {
                    message = t.getMessage();
                } else {
                    message = "网络链接不稳定，请稍后重试";
                }
            }
        } else if (t instanceof JsonSyntaxException) {
            if (BuildConfig.BUILD_TYPE.equals("release") && !BuildConfig.DEBUG) {
                message = "网络链接不稳定，请稍后重试";
            } else {
                message = "请检查您的接口解析是否正确";
            }
        } else if (t instanceof IllegalStateException || t instanceof NumberFormatException) {
            MLog.e("api", "onFailure: " + t);
        } else {
            if (!TextUtils.isEmpty(t.getMessage())) {
                message = t.getMessage();
            } else {
                message = "网络链接不稳定，请稍后重试";
            }
        }
        MLog.e("api", "url=" + call.request().url().toString() + " ----onFailure: " + t);
        if (!TextUtils.isEmpty(message)) {
            if (BuildConfig.BUILD_TYPE.equals("release") && !BuildConfig.DEBUG) {
                if (message.contains("For") || message.contains("for") || message.contains("input") || message.contains("string") ||
                        message.contains("接口请求失败") ||
                        message.contains("数据加载异常") ||
                        message.contains("推荐")) {
                    message = "";
                }
            }
        } else {
            message = "网络链接不稳定，请稍后重试";
        }
        MToast.showToast(AppManagerHelper.getAppManagerHelper().currentActivity(), message);
    }

    /**
     * 失败带返回体数据
     */
    public void onFailureWithEntity(BaseEntity entity) {

    }


    /**
     * 统一处理 State ！= ok 的Code 事件
     *
     * @param entity
     * @return
     */
    public String onFailureWithCode(BaseEntity entity) {
        String code = TextUtils.isEmpty(entity.getCode()) ? "200" : entity.getCode();
        String message = TextUtils.isEmpty(entity.getMsg()) ? "" : entity.getMsg();
        switch (code) {
            case "200":
                if (TextUtils.isEmpty(entity.getMsg())) {
                    message = "接口响应失败";
                }
                break;
            case "666":
                //登录失效
                cleanTokenInfo();
                message = entity.getMsg();
                break;
            case "500":
                message = onFailureSwitchErrCode(entity);
                break;
            default:
                break;
        }
        message = TextUtils.isEmpty(message) ? "" : message;
        if (message.contains("401") || message.contains("403") || message.contains("500") || message.contains("凭证失效") || message.contains("身份失效") ||
                message.contains("身份校验") || message.contains("凭证无效") || message.contains("身份验证失败") || message.contains("Missing")
                || message.contains("身份校验失败")) {
            message = "不允许访问";
        }
        return message;
    }

    /**
     * 统一处理 500 后的 ErrCode 处理方式
     * errCode  格式：ABBXXX
     * 这种格式：A=1 后端表单校验异常，
     * 2 业务操作不满足要求异常，
     * 4 权限异常，
     * 5 系统异常，
     * 6 需退出登录
     * BB=各自微服务的编号
     * XXX=自己服务的异常码
     *
     * @param entity
     * @return
     */
    protected String onFailureSwitchErrCode(BaseEntity entity) {
        String message = TextUtils.isEmpty(entity.getMsg()) ? "" : entity.getMsg();
        String errCode = TextUtils.isEmpty(entity.getErrCode()) ? "" : entity.getErrCode();
        String code = "0";
        if (errCode.length() == 6) {
            code = errCode.substring(0, 1);
        }
        switch (code) {
            case "1"://后端表单校验异常
                break;
            case "2"://业务操作不满足要求异常
                break;
            case "4"://权限异常
                break;
            case "5"://系统异常
                //处理系统报错异常
                message = setErroMessage(entity.getMsg());
                break;
            case "6": //需退出登录
                cleanTokenInfo();
                message = entity.getMsg();
                break;
        }
        return message;
    }

    /**
     * 处理系统报错异常
     *
     * @param msg
     * @return
     */
    private String setErroMessage(String msg) {
        String message = "";
        if (BuildConfig.BUILD_TYPE.equals("release") && !BuildConfig.DEBUG) {
            message = !TextUtils.isEmpty(msg) && msg.contains("http")?"":msg;
        } else {
            if (!TextUtils.isEmpty(msg)) {
                if (msg.contains("500") || msg.contains("401") || msg.contains("403")) {
                    try {
                        BaseEntity baseEntity = new Gson().fromJson(msg, BaseEntity.class);
                        message = baseEntity.getMsg();
                    } catch (Exception e) {
                        message = "";
                    }

                } else {
                    message = msg;
                }
            }
        }
        return message;
    }

    /**
     * 清除登录信息
     */
    private void cleanTokenInfo() {
        SharedPreferenceUtil.getInstance().saveData(SharedPreferenceUtil.LOGIN_TOKEN, "");
        SharedPreferenceUtil.getInstance().saveData(SharedPreferenceUtil.LOGIN_PC_TOKEN, "");
        SharedPreferenceUtil.getInstance().saveData(SharedPreferenceUtil.resourceAPPToken, "");
        SharedPreferenceUtil.getInstance().saveData(SharedPreferenceUtil.resourcePCToken, "");
        EventBus.getDefault().postSticky(new LoginTokenEvent());
    }
}
